利用KV Cache、Prompt Cache优化LLM推理

一句话总结:尽量把System Prompt中不变的部分放前面,变量放最后,最后是变量单独抽离成第二条System Prompt。


1. 核心推理加速器:KV Cache与自回归解码

1.1 技术原理:Transformer架构的计算瓶颈

要理解KV Cache,必须回归到Transformer模型的自注意力(Self-Attention)机制。在自回归(Autoregressive)的解码过程中,为了生成序列中的第 N 个Token,模型必须计算该Token的查询向量(Query, Q)与前面全部 N-1 个Token的键向量(Key, K)和值向量(Value, V)之间的注意力权重。

若无缓存,每次生成新Token都需要重新计算前面所有Token的 KV 向量,这将导致巨大的冗余计算。随着序列长度的增加,注意力计算的复杂度接近 O(N2),使朴素的解码过程效率低下。

1.2 KV Cache的实现机制

KV Cache的本质,是在一次生成任务的生命周期内,缓存并复用所有已处理Token的键/值向量。其工作流程分为两个核心阶段:

  1. 预填充(Prefill Phase):

    • 当推理引擎接收到输入Prompt(长度为 N)时,它会执行一次并行的前向传播(Forward Pass)。

    • 在此过程中,模型为输入序列中的每一个Token计算出其对应的 (K, V) 向量对。

    • 这些 (K, V) 对(本质上是两个Tensor,形状通常为 [batch_size, num_heads, sequence_length, head_dim])被完整地存入GPU显存中的一块指定区域。这个存储区域就是KV Cache。

    • 此阶段的延迟与输入Prompt的长度 N 成正比,即 即 Tdecode​∝M。对于长上下文,这是初始延迟的主要来源。

  2. 解码(Decoding Phase):

    • 此阶段以自回归方式循环执行,以生成 M 个新的Token。

    • 在生成第 i 个新Token时(i 从1到 M),引擎仅需为当前这一个Token计算其 Q 向量。

    • 然后,这个新的 Q 向量会与KV Cache中已存储的全部 N + i - 1(K, V) 对进行注意力计算。

    • 生成新Token后,该Token自身的 (K, V) 对会被计算并**追加(append)**到KV Cache中,使其尺寸增大。

    • 此阶段延迟与生成Token的数量 M 成正比,即 ![](data:,)。

1.3 对Prompt工程的启示

KV Cache是推理引擎的固有机制,其优化并非“是否启用”,而是“如何高效利用”。


2. 系统级吞吐优化:Prefix Caching

Prefix Caching(或Prompt Cache)是一种构建在KV Cache之上的、更高层级的系统架构优化。它解决的是不同API请求之间的冗余计算问题。

2.1 技术原理:跨请求复用KV Cache状态

在诸如多轮对话或RAG的场景中,大量的API请求拥有完全相同的前缀(例如,一个数千Token的System Prompt或文档上下文)。每次都为这个不变的前缀执行昂贵的Prefill操作,是对计算资源的极大浪费。

Prefix Caching通过在服务端持久化存储特定前缀的KV Cache来实现优化:

  1. 首次请求与缓存写入:当一个请求到达时,API网关或负载均衡层会检查其Prompt前缀。对于一个可缓存的前缀,系统会正常执行Prefill,但在完成后,将生成的KV Cache Tensor状态连同一个根据前缀内容计算出的唯一Key(如SHA256哈希),存入一个高速的分布式缓存系统(如Redis)。

  2. 后续请求与缓存命中:当另一个请求到达时,系统计算其前缀的Key。如果在缓存系统中找到了匹配的Key,则发生缓存命中

  3. 跳过Prefill:系统会直接从缓存中读取KV Cache数据,并将其“注入”或“加载”到分配给该请求的推理引擎实例中。对于这个前缀,代价高昂的Prefill阶段被完全跳过。

  4. 增量处理与解码:推理引擎仅需对请求中剩余的、动态的后缀(Suffix)部分执行Prefill,然后将其生成的KV Cache与从缓存加载的KV Cache合并,即可直接进入Decoding阶段。

2.2 对Prompt工程的启示

与KV Cache的普适性不同,有效利用Prefix Caching对Prompt工程提出了严格且明确的要求。

工程范例:

Python

# 反模式:动态信息污染前缀,导致缓存失效
messages = [
    {"role": "system", "content": f"System prompt... User info: {user_id}"}, # user_id 变化导致缓存失效
    {"role": "user", "content": "User's actual query."}
]

# 最佳实践:严格分离静态前缀与动态后缀
static_prefix = [
    {"role": "system", "content": "A very long, static system prompt..."}
]
dynamic_suffix = [
    {"role": "system", "content": f"Context: User ID is {user_id}."},
    {"role": "user", "content": "User's actual query."}
]
messages = static_prefix + dynamic_suffix

3. 机制对比与总结

对比维度 KV Cache Prefix Caching (Prompt Cache)
作用层级 模型推理内核 (Inference Kernel) 服务架构层 (System Architecture)
生命周期 单次API请求 跨多次API请求,由服务端策略管理
优化对象 自回归解码中的冗余计算 多个请求间对相同前缀的冗余Prefill
核心原理 缓存并复用已处理Token的(K, V) Tensor 持久化并复用特定前缀的完整KV Cache状态
工程策略 结构化、排序、精简Prompt以优化单次性能和质量 严格分离静态与动态内容以触发跨请求缓存

结论

KV Cache与Prefix Caching构成了LLM推理优化的双层体系。KV Cache是基础,保证了单次生成任务的内部效率;而Prefix Caching是建立在此之上的高级架构模式,通过跨请求复用计算结果,显著降低了长上下文应用场景下的延迟与计算成本。作为AI工程师,深刻理解这两种机制的内在原理与边界条件,并将其映射到具体的Prompt工程策略中,是从根本上构建高性能、可扩展、经济高效的LLM系统的关键。